<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>3_react生命周期(新)</title>
    <script
      crossorigin
      src="https://unpkg.com/react@18/umd/react.development.js"
    ></script>
    <script
      crossorigin
      src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"
    ></script>
    <script src="../React-js//babel.min.js"></script>
    <style>
      @import 'https://unpkg.com/open-props@1.5.0/open-props.min.css';
      @import 'https://unpkg.com/open-props/normalize.min.css';
      button {
        padding: 10px;
        margin: 20px;
        border-radius: 7px;
      }
    </style>
  </head>
  <body>
    <div id="root"></div>

    <script type="text/babel">
      /**
       *  1.初始化阶段: 由ReactDOM.render()触发 -- 初次渲染
       *        1.  constructor()
       *        2.  getDerivedStateFromProps
       *        3.  render()
       *        4.  componentDidMount()  ==> 常用
       *          ==>一般在这个钩子中做一些初始化的事。例如：开启定时器、发送网络请求、订阅消息
       *
       * 2.更新阶段: 由组件内部 this.setState() 或 父组件重新 render 触发
       *        1. getDerivedStateFromProps
       *        2. shouldComponentUpdate()
       *        3. render()   (渲染)==> 必须使用的一个
       *        4. componentDidUpdate()
       *
       * 3.卸载组件: 有ReactDOM.unmountComponentAtNode()触发
       *        1. componentWillUnmount() ==> 常用
       *           ==>一般在这个钩子中做一些收尾的事。例如：关闭定时器、取消订阅消息
       *
       */
      class Count extends React.Component {
        // 构造器
        constructor(props) {
          console.log('count--constructor');
          super(props);
          this.state = { count: 0 };
        }

        // 加一按钮回调
        add = () => {
          const { count } = this.state;
          this.setState({ count: count + 1 });
        };
        // 卸载组件按钮的回调
        death = () => {
          ReactDOM.unmountComponentAtNode(document.getElementById('root'));
        };
        // 强制更新按钮的回调
        force = () => {
          this.forceUpdate();
        };

        // 若 state 的值在任何时候都取决与props，那么可以使用
        static getDerivedStateFromProps(props, state) {
          console.log('getDerivedStateFromProps', props, state);
          return null;
          // return { count: 199 };
          // return { count: props.name };
          // return props;
        }

        getSnapshotBeforeUpdate() {
          console.log('getSnapsShotBeforeUpdate');
          // return null;
          return 'cxh';
        }

        // 组件挂载完毕的钩子
        componentDidMount() {
          console.log('count--componentDidMount');
        }

        // 组件将要卸载的钩子
        componentWillUnmount() {}

        // 控制组件更新的"阀门"
        shouldComponentUpdate() {
          console.log('count--shouldComponentUpdate');
          return true;
        }

        // 组件更新完毕
        componentDidUpdate(prevProps, prevState, snapShopValue) {
          console.log(prevProps, prevState, snapShopValue);
          console.log('count--componentDidUpdate');
        }

        render() {
          console.log('count--render');
          return (
            <div>
              <h2>当前求和为:{this.state.count}</h2>
              <button onClick={this.add}>点我加1</button>
              <button onClick={this.death}>卸载</button>
              <button onClick={this.force}>
                不更改任何状态中的数据，强制更新一下
              </button>
            </div>
          );
        }
      }

      // 渲染组件
      const root = ReactDOM.createRoot(document.getElementById('root'));
      root.render(<Count name="哈哈" count="999" />);
    </script>
  </body>
</html>
